#include "Subsystem/ItemManager/RoomLightManagerSubsystem.h"

#include "Subsystem/RoomManager/RoomManagerFunctionLibrary.h"
#include "Subsystem/RoomManager/RoomManagerSubsystem.h"

void URoomLightManagerSubsystem::Initialize(FSubsystemCollectionBase& Collection)
{
	Super::Initialize(Collection);
}

void URoomLightManagerSubsystem::Deinitialize()
{
	Super::Deinitialize();
}

TArray<UActorComponent*> URoomLightManagerSubsystem::GetRoomComponentsByClass(const FName& RoomName, TSubclassOf<UActorComponent> ComponentClass)
{
	TArray<UActorComponent*> Components;
	if (!RoomLightInfoMap.Contains(RoomName))
	{
		UE_LOG(LogTemp, Error, TEXT("RoomName [%s] not found."), *RoomName.ToString());
		return Components;
	}
	FRoomLightInfo& LightInfo = RoomLightInfoMap[RoomName];
	for (TObjectPtr<AActor> RoomLight : LightInfo.RoomLights)
	{
		Components.Append(RoomLight->K2_GetComponentsByClass(ComponentClass));
	}
	return Components;
}

void URoomLightManagerSubsystem::StartGame()
{
	URoomManagerSubsystem* RoomManagerSubsystem = GetWorld()->GetGameInstance()->GetSubsystem<URoomManagerSubsystem>();
	if (!RoomManagerSubsystem)
	{
		UE_LOG(LogTemp, Error, TEXT("RoomManagerSubsystem not found when StartGame."));
		return;
	}

	CollectLightInfos(RoomManagerSubsystem);
	EnsureLightInfos();
}

void URoomLightManagerSubsystem::FinishGame()
{
	URoomManagerSubsystem* RoomManagerSubsystem = GetWorld()->GetGameInstance()->GetSubsystem<URoomManagerSubsystem>();
	if (!RoomManagerSubsystem)
	{
		UE_LOG(LogTemp, Error, TEXT("RoomManagerSubsystem not found when FinishGame."));
		return;
	}
}

void URoomLightManagerSubsystem::RegisterElectricSwitch(AActor* InElectricSwitch)
{
	ensureAlwaysMsgf(!IsValid(ElectricSwitch), TEXT("ElectricSwitch [%s] already registered."), *InElectricSwitch->GetName());
	ElectricSwitch = InElectricSwitch;
}

void URoomLightManagerSubsystem::UnregisterElectricSwitch(AActor* InElectricSwitch)
{
}

void URoomLightManagerSubsystem::RegisterRoomSwitch(AActor* InRoomSwitch)
{
	ensureAlwaysMsgf(!RoomSwitches.Contains(InRoomSwitch), TEXT("RoomSwitch [%s] already registered."), *InRoomSwitch->GetName());
	RoomSwitches.Add(InRoomSwitch);
}

void URoomLightManagerSubsystem::UnregisterRoomSwitch(AActor* InRoomSwitch)
{
}

void URoomLightManagerSubsystem::RegisterRoomLight(AActor* InRoomLight)
{
	ensureAlwaysMsgf(!RoomLights.Contains(InRoomLight), TEXT("RoomLight [%s] already registered."), *InRoomLight->GetName());
	RoomLights.Add(InRoomLight);
}

void URoomLightManagerSubsystem::UnregisterRoomLight(AActor* InRoomLight)
{
}

void URoomLightManagerSubsystem::CollectLightInfos(const URoomManagerSubsystem* RoomManagerSubsystem)
{
	for (TObjectPtr<AActor> RoomSwitch : RoomSwitches)
	{
		FName RoomName = RoomManagerSubsystem->GetActorRoomName(RoomSwitch);
		FRoomLightInfo& LightInfo = RoomLightInfoMap.FindOrAdd(RoomName);
		LightInfo.RoomName = RoomName;
		LightInfo.RoomSwitches.Add(RoomSwitch);
	}

	for (TObjectPtr<AActor> RoomLight : RoomLights)
	{
		FName RoomName = RoomManagerSubsystem->GetActorRoomName(RoomLight);
		FRoomLightInfo& LightInfo = RoomLightInfoMap.FindOrAdd(RoomName);
		LightInfo.RoomName = RoomName;
		LightInfo.RoomLights.Add(RoomLight);
	}
}

void URoomLightManagerSubsystem::EnsureLightInfos()
{
	ensureAlwaysMsgf(IsValid(ElectricSwitch), TEXT("ElectricSwitch not registered."));

	for (auto& Element : RoomLightInfoMap)
	{
		FRoomLightInfo& LightInfo = Element.Value;
		ensureAlwaysMsgf(URoomManagerFunctionLibrary::IsValidRoomName(LightInfo.RoomName), TEXT("RoomName [%s] is invalid."), *LightInfo.RoomName.ToString());
		ensureAlwaysMsgf(!LightInfo.RoomSwitches.IsEmpty(), TEXT("RoomName [%s] Switch is empty."), *LightInfo.RoomName.ToString());
		if (LightInfo.RoomSwitches.Num() >= 2)
		{
			UE_LOG(LogTemp, Warning, TEXT("RoomName [%s] Switch is more than 2."), *LightInfo.RoomName.ToString());
		}
		ensureAlwaysMsgf(!LightInfo.RoomLights.IsEmpty(), TEXT("RoomName [%s] Light is empty."), *LightInfo.RoomName.ToString());
	}
}
